home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP05.ZIP / CHAP05 / SMASHER / SMASHER.CPP < prev    next >
C/C++ Source or Header  |  1993-03-28  |  9KB  |  342 lines

  1. /*
  2.  * SMASHER.CPP
  3.  *
  4.  * Functions to demonstrate a File Manager extension DLL that implements
  5.  * a toolbar button to defragment selected compound files.
  6.  *
  7.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved.
  8.  *
  9.  * Kraig Brockschmidt, Software Design Engineer
  10.  * Microsoft Systems Developer Relations
  11.  *
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  *
  15.  */
  16.  
  17.  
  18. #include <windows.h>
  19. #include <ole2.h>
  20. #include "wfext.h"              //Windows for Workgroups version.
  21. #include "smasher.h"
  22.  
  23.  
  24. HINSTANCE   g_hInst;
  25. BOOL        fInitialized;
  26.  
  27.  
  28. //Toolbar to place on Windows for Workgroups File Manager.
  29. EXT_BUTTON btns[1]={{IDM_SMASH, IDS_SMASHHELP+1, 0}};
  30.  
  31.  
  32. /*
  33.  * LibMain
  34.  *
  35.  * Purpose:
  36.  *  DLL-specific entry point called from LibEntry.  Initializes
  37.  *  global variables and loads standard image bitmaps.
  38.  *
  39.  * Parameters:
  40.  *  hInstance       HINSTANCE instance of the DLL.
  41.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  42.  *  wHeapSize       WORD byte count of the heap.
  43.  *  lpCmdLine       LPSTR to command line used to start the module.
  44.  *
  45.  * Return Value:
  46.  *  HANDLE          Instance handle of the DLL.
  47.  */
  48.  
  49. HANDLE FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSeg
  50.     , WORD cbHeapSize, LPSTR lpCmdLine)
  51.     {
  52.     //Remember our instance.
  53.     g_hInst=hInstance;
  54.  
  55.     if (0!=cbHeapSize)
  56.         UnlockData(0);
  57.  
  58.     return hInstance;
  59.     }
  60.  
  61.  
  62.  
  63.  
  64.  
  65. /*
  66.  * WEP
  67.  *
  68.  * Purpose:
  69.  *  Required DLL Exit function.  Does nothing.
  70.  *
  71.  * Parameters:
  72.  *  bSystemExit     BOOL indicating if the system is being shut
  73.  *                  down or the DLL has just been unloaded.
  74.  *
  75.  * Return Value:
  76.  *  void
  77.  *
  78.  */
  79.  
  80. void FAR PASCAL WEP(int bSystemExit)
  81.     {
  82.     return;
  83.     }
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91. /*
  92.  * FMExtensionProc
  93.  *
  94.  * Purpose:
  95.  *  File Manager Extension callback function, receives messages from
  96.  *  file manager when extension toolbar buttons and commands are
  97.  *  invoked.
  98.  *
  99.  * Parameters:
  100.  *  hWnd            HWND of File Manager.
  101.  *  iMsg            UINT message identifier
  102.  *  lParam          LONG extra information.
  103.  *
  104.  * Return Value:
  105.  *  HMENU
  106.  */
  107.  
  108. HMENU FAR PASCAL FMExtensionProc(HWND hWnd, UINT iMsg, LONG lParam)
  109.     {
  110.     HMENU               hMenu=NULL;
  111.     HRESULT             hr;
  112.     LPMALLOC            pIMalloc;
  113.     LPFMS_LOAD          pLoad;
  114.     LPFMS_TOOLBARLOAD   pTool;
  115.     LPFMS_HELPSTRING    pHelp;
  116.  
  117.     switch (iMsg)
  118.         {
  119.         case FMEVENT_LOAD:
  120.             pLoad=(LPFMS_LOAD)lParam;
  121.             pLoad->dwSize=sizeof(FMS_LOAD);
  122.  
  123.             /*
  124.              * Check if our host did CoInitialize by trying CoGetMalloc.
  125.              * If it doesn't work, then we'll CoInitialize ourselves.
  126.              */
  127.             hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
  128.  
  129.             if (SUCCEEDED(hr))
  130.                 pIMalloc->Release();
  131.             else
  132.                 {
  133.                 hr=CoInitialize(NULL);
  134.  
  135.                 if (FAILED(hr))
  136.                     return NULL;
  137.  
  138.                 fInitialized=TRUE;
  139.                 }
  140.  
  141.             //Assign the popup menu name for extension
  142.             LoadString(g_hInst, IDS_SMASH, pLoad->szMenuName
  143.                 , sizeof(pLoad->szMenuName));
  144.  
  145.             //Load the popup menu
  146.             pLoad->hMenu=LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
  147.  
  148.             return pLoad->hMenu;
  149.  
  150.  
  151.         case FMEVENT_UNLOAD:
  152.             if (fInitialized)
  153.                 CoUninitialize();
  154.             break;
  155.  
  156.  
  157.         case FMEVENT_TOOLBARLOAD:
  158.             /*
  159.              * File Manager has loaded our toolbar extension, so fill
  160.              * the TOOLBARLOAD structure with information about our
  161.              * buttons.  This is only for Windows for Workgroups.
  162.              */
  163.  
  164.             pTool=(LPFMS_TOOLBARLOAD)lParam;
  165.             pTool->lpButtons= (LPEXT_BUTTON)&btns;
  166.             pTool->cButtons = 1;
  167.             pTool->cBitmaps = 1;
  168.             pTool->idBitmap = IDR_BITMAP;
  169.             break;
  170.  
  171.  
  172.         case FMEVENT_HELPSTRING:
  173.             //File Manager is requesting a status-line help string.
  174.             pHelp=(LPFMS_HELPSTRING)lParam;
  175.  
  176.             LoadString(g_hInst, IDS_SMASHHELP+pHelp->idCommand
  177.                        , pHelp->szHelp, sizeof(pHelp->szHelp));
  178.  
  179.             break;
  180.  
  181.  
  182.         case IDM_SMASH:
  183.             SmashSelectedFiles(hWnd);
  184.             break;
  185.         }
  186.  
  187.     return hMenu;
  188.     }
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197. /*
  198.  * SmashSelectedFiles
  199.  *
  200.  * Purpose:
  201.  *  Retrieves the list of selected files from File Manager and
  202.  *  attempts to compress each one.
  203.  *
  204.  * Parameters:
  205.  *  hWnd            HWND of the File Manager message processing window
  206.  *                  that we send messages to in order to retrieve the
  207.  *                  count of selected files and their filenames.
  208.  *
  209.  * Return Value:
  210.  *  BOOL            TRUE if the function was successful, FALSE otherwise.
  211.  */
  212.  
  213. BOOL SmashSelectedFiles(HWND hWnd)
  214.     {
  215.     FMS_GETFILESEL  fms;
  216.     UINT            cFiles;
  217.     UINT            i;
  218.     LPSTR           pszErr;
  219.     HRESULT         hr;
  220.     STATSTG         st;
  221.     OFSTRUCT        of;
  222.     LPMALLOC        pIMalloc;
  223.     LPSTORAGE       pIStorageOld;
  224.     LPSTORAGE       pIStorageNew;
  225.  
  226.     /*
  227.      * Retrieve information from File Manager about the selected
  228.      * files and allocate memory for the paths and filenames.
  229.      */
  230.  
  231.     //Get the number of selected items.
  232.     cFiles=(UINT)SendMessage(hWnd, FM_GETSELCOUNT, 0, 0L);
  233.  
  234.     //Nothing to do, so quit.
  235.     if (0==cFiles)
  236.         return TRUE;
  237.  
  238.     //Get error string memory
  239.     hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
  240.  
  241.     if (FAILED(hr))
  242.         return FALSE;
  243.  
  244.     pszErr=(LPSTR)pIMalloc->Alloc(1024);
  245.  
  246.     /*
  247.      * Enumerate the selected files and directories using the FM_GETFILESEL
  248.      * message to the File Manager window.  For each file, check if its
  249.      * a Compound File (StgIsStorageFile) and if not, skip it.
  250.      *
  251.      * If it is a compound file, then create a temp file and ::CopyTo
  252.      * from old to new.  If this works, then we reopen the old file
  253.      * in overwrite mode and ::CopyTo back into it.
  254.      */
  255.  
  256.     for (i = 0; i < cFiles; i++)
  257.         {
  258.         SendMessage(hWnd, FM_GETFILESEL, i, (LONG)(LPSTR)&fms);
  259.  
  260.         //Skip non-storages.
  261.         hr=StgIsStorageFile(fms.szName);
  262.  
  263.         if (FAILED(hr))
  264.             {
  265.             wsprintf(pszErr, SZERRNOTACOMPOUNDFILE, (LPSTR)fms.szName);
  266.             MessageBox(hWnd, pszErr, SZSMASHER, MB_OK | MB_ICONHAND);
  267.             continue;
  268.             }
  269.  
  270.         /*
  271.          * Create a temporary Compound File.  We don't use DELETEONRELEASE
  272.          * in case we have to save it when coying over the old file fails.
  273.          */
  274.         hr=StgCreateDocfile(NULL, STGM_CREATE | STGM_DIRECT | STGM_READWRITE
  275.             | STGM_SHARE_EXCLUSIVE, 0, &pIStorageNew);
  276.  
  277.         if (FAILED(hr))
  278.             {
  279.             MessageBox(hWnd, SZERRTEMPFILE, SZSMASHER, MB_OK | MB_ICONHAND);
  280.             continue;
  281.             }
  282.  
  283.         //Open the existing file as read-only
  284.         hr=StgOpenStorage(fms.szName, NULL, STGM_DIRECT | STGM_READ
  285.             | STGM_SHARE_DENY_WRITE, NULL, 0, &pIStorageOld);
  286.  
  287.         if (FAILED(hr))
  288.             {
  289.             pIStorageNew->Release();
  290.             wsprintf(pszErr, SZERROPENFAILED, (LPSTR)fms.szName);
  291.             MessageBox(hWnd, pszErr, SZSMASHER, MB_OK | MB_ICONHAND);
  292.             continue;
  293.             }
  294.  
  295.         /*
  296.          * Compress with ::CopyTo.  Since the temp is opened in
  297.          * direct mode, changes are immediate.
  298.          */
  299.         hr=pIStorageOld->CopyTo(NULL, NULL, NULL, pIStorageNew);
  300.         pIStorageOld->Release();
  301.  
  302.         if (FAILED(hr))
  303.             {
  304.             pIStorageNew->Release();
  305.             MessageBox(hWnd, SZERRTEMPFILECOPY, SZSMASHER, MB_OK | MB_ICONHAND);
  306.             continue;
  307.             }
  308.  
  309.         //Temp file contains the defragmented copy now, try copying back.
  310.         hr=StgOpenStorage(fms.szName, NULL, STGM_DIRECT | STGM_CREATE
  311.             | STGM_WRITE | ST